package timing.ukulele.third.msgChannel.handle.impl;

import cn.jiguang.common.resp.APIConnectionException;
import cn.jiguang.common.resp.APIRequestException;
import cn.jpush.api.JPushClient;
import cn.jpush.api.push.PushResult;
import cn.jpush.api.push.model.Options;
import cn.jpush.api.push.model.Platform;
import cn.jpush.api.push.model.PushPayload;
import cn.jpush.api.push.model.audience.Audience;
import cn.jpush.api.push.model.notification.Notification;
import com.alibaba.fastjson2.JSON;
import com.google.common.base.Throwables;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import timing.ukulele.third.dictionary.msg.MsgChannelType;
import timing.ukulele.third.msgChannel.handle.BaseHandler;
import timing.ukulele.third.msgChannel.model.RecallTaskInfo;
import timing.ukulele.third.msgChannel.model.SendTaskInfo;
import timing.ukulele.third.msgChannel.model.account.JGAccount;
import timing.ukulele.third.msgChannel.model.content.PushContentModel;
import timing.ukulele.third.msgChannel.param.HandleMessageBaseResponse;
import timing.ukulele.third.msgChannel.utils.AccountUtils;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * 极光通知栏消息发送处理
 * https://docs.jiguang.cn/jpush/server/push/server_overview
 *
 * @author zh
 */
@Component
@Slf4j
public class JGPushHandler extends BaseHandler {

    @Autowired
    private AccountUtils accountUtils;

    public JGPushHandler() {
        channelCode = MsgChannelType.JGPush.getCode();
    }

    @Override
    public HandleMessageBaseResponse send(SendTaskInfo taskInfo) {
        // 构造返回值
        HandleMessageBaseResponse result = new HandleMessageBaseResponse();
        try {
            JGAccount account = accountUtils.getAccountById(taskInfo.getSendAccountId(), JGAccount.class);

            PushContentModel pushContentModel = (PushContentModel)taskInfo.getContentModel();
            // 构建语音参数
            Map<String, String> extras = new HashMap<>();
            // 这个要和前端约定好，暂时先用诺达云的实现传参
            extras.put("content_type", "1");
            extras.put("title", pushContentModel.getTitle());
            extras.put("msg_content", pushContentModel.getContent());

            // 构建Android消息体（暂时实现安卓，IOS方法也写了，后续看是Android和IOS一起同步调用，还是传参决定发送哪个手机操作系统）
            PushPayload pushPayloadAndroid = buildAndroidPushPayload(pushContentModel, taskInfo.getReceiver(), extras);

            // 请求极光消息推送
            JPushClient jPushClient = new JPushClient(account.getSecret(), account.getAppKey());
            PushResult pushResult = jPushClient.sendPush(pushPayloadAndroid);
            log.info("JGPushHandler#send response:{},params:{}", JSON.toJSONString(pushResult), JSON.toJSONString(taskInfo));
            if (pushResult != null && pushResult.isResultOK()) {
                result.setHandleFlag(true);
            } else {
                result.setHandleFlag(false);
            }
        }catch (APIRequestException e) {
            log.error("JGPushHandler#send fail!e:{},params:{}", e.getErrorMessage(), JSON.toJSONString(taskInfo));
            result.setHandleFlag(false);
            result.setHandleMessage(e.getErrorMessage());
        } catch (Exception e) {
            log.error("JGPushHandler#send fail!e:{},params:{}", Throwables.getStackTraceAsString(e), JSON.toJSONString(taskInfo));
            result.setHandleFlag(false);
            result.setHandleMessage(Throwables.getStackTraceAsString(e));
        }
        return result;
    }

    /**
     * 构建Android消息体
     * @param pushContentModel
     * @param reciverSet
     * @param extras
     * @return
     */
    private PushPayload buildAndroidPushPayload(PushContentModel pushContentModel, Set<String> reciverSet, Map<String, String> extras) {
        // 构建消息体
        Notification notificationAndroid = Notification.android(pushContentModel.getContent(), "", extras);
        return PushPayload.newBuilder()
                .setPlatform(Platform.android())
                .setAudience(Audience.alias(reciverSet))
                .setNotification(notificationAndroid)
                .build();
    }

    /**
     * 构建IOS消息体
     * @param pushContentModel
     * @param reciverSet
     * @param extras
     * @return
     */
    private PushPayload buildIOSPushPayload(PushContentModel pushContentModel, Set<String> reciverSet, Map<String, String> extras) {
        // 构建消息体
        Notification notificationIOS = Notification.ios(pushContentModel.getContent(), extras);
        return PushPayload.newBuilder()
                .setPlatform(Platform.ios())
                .setAudience(Audience.alias(reciverSet))
                .setOptions(Options.newBuilder()
                        .setApnsProduction(false)
                        .build())
                .setNotification(notificationIOS)
                .build();
    }

    /**
     * 撤销操作首先会从服务端尝试撤销（Android 消息，排队中 / 发送中状态可以服务端撤销；iOS 消息，排队中状态可以服务端撤销）；
     * 其次，针对 Push SDK（JPush Android SDK v3.5.0 及以上和 JPush iOS SDK v3.2.8 及以上），会尝试从设备端撤销已展示但未被点击的消息。
     * （目前Android厂商本身支持且极光已经适配的主要是小米、vivo）
     * 【未实现】
     * https://docs.jiguang.cn/jpush/server/push/rest_api_v3_push_advanced
     * @param recallTaskInfo
     */
    @Override
    public HandleMessageBaseResponse recall(RecallTaskInfo recallTaskInfo) {
        return HandleMessageBaseResponse.builder().handleFlag(true).build();
    }

}
